<template>
  <div>
    <recycle-scroller class="playlist-scroller"
      ref="scroller"
      :items="playlists"
      :item-size="itemSize"
      :buffer="600"
      key-filed="id"
      page-mode
      emit-update
      @resize="onResize"
      @update="onUpdate">

      <template v-slot="{ item }">
        <div class="playlist-row">
          <base-playlist-item class="playlist-item"
            v-for="(cell, index) of item.list" :key="index"
            :width="itemWidth + 'px'"
            :id="cell.id"
            :img="cell.coverImgUrl"
            :playcount="cell.playCount"
            :desc="cell.description"/>
        </div>
      </template>

      <template #after>
        <base-loading-spinner v-show="loading"
          width="30px"
          height="30px"
          color="rgb(238, 10, 36)"
          itemWidth="8%"/>
        <div v-if="!loading && !hasMore"
          class="playlist-nomore">
          <p>没有更多数据了</p>
        </div>
      </template>
    </recycle-scroller>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'

export default {
  name: 'infinite-scroll',
  props: {
    cat: { type: String, default: '' }
  },
  data () {
    return {
      loading: true,
      cache: [], // 所有歌单
      playlists: [], // 以 3 个为一组的二维数组
      limit: 30, // 每次请求加载的数据
      threshold: 200, // 距离底部的阈值，此时将触发一次数据的请求(由于 update 事件的触发间隔较大，建议此值不要小于 itemSize)
      hasMore: true // 是否还有更多的数据可以请求
    }
  },
  mounted () {
    this.getPlaylist()
  },
  computed: {
    ...mapGetters(['bodyWidth']),
    itemWidth () {
      return this.bodyWidth * 0.3
    },
    itemSize () {
      return this.itemWidth * 1.5
    },
    scroller () {
      return this.$refs.scroller.getScroll()
    }
  },
  methods: {
    onResize () {
      console.log('size change, now size: ', this.cache.length)
    },
    onUpdate (start, end) {
      const scrollTop = this.$refs.scroller.getScroll().end
      if (this.hasMore &&
          !this.loading && // 保证仅触发一次
          scrollTop > 1000 && // 该事件会自动刷新一次，设置一个阈值判定当滚动后才触发
          scrollTop + this.threshold >= this.itemSize * this.playlists.length
      ) {
        console.log('scrollTop is %d, now to fetch data...', scrollTop)
        this.getPlaylist(this.cat, this.cache.length)
      }
    },
    getPlaylist (cat, offset) {
      this.loading = true
      setTimeout(async () => {
        let res
        try {
          res = await this.$api.getTopPlaylist({
            cat: this.cat,
            limit: this.limit,
            offset: this.cache.length
          })
        } catch (e) {
          this.loading = false
          this.$toast.fail({
            text: '数据加载错误!'
          })
          return
        }

        const { data } = res
        this.hasMore = data.more
        this.cache = this.cache.concat(data.playlists)
        this.playlists = this.to3ColList(this.cache)
        this.loading = false
      }, 500)
    },
    // 每行 3 个歌单，需要将数据拆分为对象数组
    to3ColList (playlists) {
      const ret = []
      for (let i = 0, l = playlists.length; i < l; i += 3) {
        const list = playlists.slice(i, i + 3)
        ret.push({ list, id: i })
      }
      return ret
    }
  }
}
</script>

<style lang="scss" scoped>
.playlist {
  &-scroller {
    width: 100%;
    height: 100%;
  }
  &-row {
    display: flex;
    justify-content: space-between;
  }
  &-nomore {
    height: .3rem;
    line-height: .3rem;
    text-align: center;
    font-size: 14px;
    color: #ccc;
  }
}
</style>
